package com.hivision.streetlight.codec;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class CmdProcess {
	// private final static String cmd_set_light_

	private String identifier = "123";
	private String msgType;
	private String serviceId = "StreetLightBasic";
	private String cmd = "SET_DEVICE_LEVEL";
	private int hasMore = 0;
	private int errcode = 0;
	private int mid = 0;
	private JsonNode paras;

	private String uid; // 设备uid
	private int cmdCode; // 指令码

	private double temperature = 0; // 温度
	private double humidity = 0; // 湿度
	private double illuminance = 0; // 光照度
	private int brightness = 0; // 亮度
	private int signalIntensity; // 信号强度
	private int errorRate; // 误码率

	private int heartBeatIntervel; // 心跳间隔
	private int uploadInterval; // 数据上报间隔
	private double maxVoltagethreshold; // 过压阈值
	private double minVoltagethreshold; // 欠压阈值
	private String iotIp; // IOT平台IP地址
	private int iotPort; // IOT平台端口
	private String newUid; // 单灯uid

	private double voltageOffset; // 电压补偿
	private double currentOffset; // 电流补偿

	private int mainVersion = 0x00; // 主版本
	private int subVersion = 0x00; // 副版本
	private int reqLength; // 请求指令长度

//	private final String CLOUDREQ = "cloudReq";
//	private final String CLOUDRSP = "cloudRsp";
//	private final int RSP_LEN = 20;
	private final int CMDCODE_INDEX = 16; // 指令码字节的位置索引
	
	private byte[] request;

	public CmdProcess() {
	}

	public CmdProcess(ObjectNode input) {

		try {
//			this.identifier = input.get("identifier").asText();
			this.msgType = input.get("msgType").asText();
			this.hasMore = 0;

			// 如果是应答
			if (msgType.equals("cloudRsp")) {
				this.request = Utilty.hexString2Bytes(input.get("request").asText());
				// 在此组装ACK的值
				this.errcode = input.get("errcode").asInt();
			}
			// 平台下发命令到设备
			else {
				this.serviceId = input.get("serviceId").asText();
				this.cmd = input.get("cmd").asText();
				this.mid = input.get("mid").intValue();
				this.paras = input.get("paras");
				
				if(this.paras.has("parameters") && this.paras.get("parameters").has("mainVersion")){
					this.mainVersion = this.paras.get("parameters").get("mainVersion").asInt();
				}
				if(this.paras.has("parameters") && this.paras.get("parameters").has("subVersion")){
					this.subVersion = this.paras.get("parameters").get("subVersion").asInt();
				}
				
				if(this.paras.has("parameters") && this.paras.get("parameters").has("uid")){
					this.uid = this.paras.get("parameters").get("uid").asText();
				}
				
				if(this.paras.has("parameters") && this.paras.get("parameters").has("cmdCode")){
					this.cmdCode = this.paras.get("parameters").get("cmdCode").asInt();
				}

				if (this.cmdCode == 0x0004) { /* 设置单灯亮度 */

//					this.cmd = "SET_BRIGHTNESS";
//					this.msgType = CLOUDREQ;
					this.brightness = this.paras.get("parameters").get("brightness").asInt();
					this.reqLength = 21;
				} else if (this.cmdCode == 0x0005) { // 重启单灯

//					this.cmd = "RESET";
					this.reqLength = 20;

				} else if (this.cmdCode == 0x0006) {/* 设置单灯参数 */

//					this.cmd = "SET_PARAMETERS";
					this.reqLength = 28;

					heartBeatIntervel = this.paras.get("parameters").get("heartBeatIntervel").asInt();
					uploadInterval = this.paras.get("parameters").get("uploadInterval").asInt();
					maxVoltagethreshold = this.paras.get("parameters").get("maxVoltagethreshold").asDouble();
					minVoltagethreshold = this.paras.get("parameters").get("minVoltagethreshold").asDouble();
				} else if (this.cmdCode == 0x0007) { // 查询单灯参数

//					this.cmd = "GET_PARAM";
					this.reqLength = 20;
				} else if (this.cmdCode == 0x0008) { // 查询单灯状态
//					this.cmd = "GET_STATUS";
					this.reqLength = 20;
				} else if (this.cmdCode == 0x0009) { // 更新固件

//					this.cmd = "UPDATE_FIRMWARE";
					int dataLength = this.paras.get("parameters").get("dataLength").asInt();
					this.reqLength = 28 + dataLength;
				} else if (this.cmdCode == 0x000A) { // 设置Iot平台地址及端口

//					this.cmd = "SET_IOT";
					this.reqLength = 26;
					iotIp = this.paras.get("parameters").get("iotIp").asText();
					iotPort = this.paras.get("parameters").get("iotPort").asInt();
				} else if (this.cmdCode == 0x000B) { // 设置单灯UID

//					this.cmd = "SET_UID";
					this.reqLength = 28;
					newUid = this.paras.get("parameters").get("newUid").asText();
				} else if (this.cmdCode == 0x000C) { // 设置单灯计量补偿

//					this.cmd = "SET_OFFSET";
					this.reqLength = 24;
					voltageOffset = this.paras.get("parameters").get("voltageOffset").asDouble();
					currentOffset = this.paras.get("parameters").get("currentOffset").asDouble();
				}else{
					System.out.println(String.format("error cmdCode [%s] can not found in CmdProcess", this.cmdCode));
					throw new Exception(String.format("error cmdCode [%s] can not found in CmdProcess", this.cmdCode));
				}
			}

			/*
			 * 平台收到设备上报消息，编码ACK { "identifier":"0", "msgType":"cloudRsp",
			 * "request": ***,//设备上报的码流 "errcode":0, "hasMore":0 }
			 */
			// if (msgType.equals("cloudRsp")) {
			// //在此组装ACK的值
			// this.errcode = input.get("errcode").asInt();
			// this.hasMore = input.get("hasMore").asInt();
			// } else {
			/*
			 * 平台下发命令到设备，输入 { "identifier":0, "msgType":"cloudReq",
			 * "serviceId":"WaterMeter", "cmd":"SET_DEVICE_LEVEL",
			 * "paras":{"value":"20"}, "hasMore":0
			 * 
			 * }
			 */
			// 此处需要考虑兼容性，如果没有传mId，则不对其进行编码
			// if (input.get("mid") != null) {
			// this.mid = input.get("mid").intValue();
			// }
			// this.cmd = input.get("cmd").asText();
			// this.paras = input.get("paras");
			// this.hasMore = input.get("hasMore").asInt();
			// }

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public byte[] toByte() {
		try {
			if (this.msgType.equals("cloudReq")) {
				
				byte[] byteRead = new byte[this.reqLength];
				int i = setBaseValue(byteRead);
				
				if (this.cmdCode == 0x0004) { /* 设置单灯亮度 */
					byteRead[i++] = (byte)this.brightness;
				} else if (this.cmdCode == 0x0005) { // 重启单灯

				} else if (this.cmdCode == 0x0006) {/* 设置单灯参数 */
					// 
					byte[] heartBeatIntervelByte = Utilty.getInstance().int2Bytes(this.heartBeatIntervel, 2);
					byteRead[i++] = heartBeatIntervelByte[0];
					byteRead[i++] = heartBeatIntervelByte[1];

					byte[] ploadIntervalByte = Utilty.getInstance().int2Bytes(this.uploadInterval, 2);
					byteRead[i++] = ploadIntervalByte[0];
					byteRead[i++] = ploadIntervalByte[1];
					
					byte[] maxVoltagethresholdByte = Utilty.getInstance().int2Bytes(new Double(this.maxVoltagethreshold*10).intValue(), 2);
					byteRead[i++] = maxVoltagethresholdByte[0];
					byteRead[i++] = maxVoltagethresholdByte[1];
					
					byte[] minVoltagethresholdByte = Utilty.getInstance().int2Bytes(new Double(this.minVoltagethreshold*10).intValue(), 2);
					byteRead[i++] = minVoltagethresholdByte[0];
					byteRead[i++] = minVoltagethresholdByte[1];

				} else if (this.cmdCode == 0x0007) { // 查询单灯参数

				} else if (this.cmdCode == 0x0008) { // 查询单灯状态
					
				} else if (this.cmdCode == 0x0009) { // 更新固件
					int offset = this.paras.get("offset").asInt();
					byte[] offsetByte = Utilty.getInstance().int2Bytes(offset, 4);
					byteRead[i++] = offsetByte[0];
					byteRead[i++] = offsetByte[1];
					byteRead[i++] = offsetByte[2];
					byteRead[i++] = offsetByte[3];
					
					int softPackLength = this.paras.get("softPackLength").asInt();
					byte[] softPackLengthByte = Utilty.getInstance().int2Bytes(softPackLength, 4);
					byteRead[i++] = softPackLengthByte[0];
					byteRead[i++] = softPackLengthByte[1];
					byteRead[i++] = softPackLengthByte[2];
					byteRead[i++] = softPackLengthByte[3];
					
					//Todo

				} else if (this.cmdCode == 0x000A) { // 设置Iot平台地址及端口
					String[] iotIpPiece = this.paras.get("iotIp").asText().split(".");
					byteRead[i++] = (byte)(Integer.valueOf(iotIpPiece[0]).intValue());
					byteRead[i++] = (byte)(Integer.valueOf(iotIpPiece[1]).intValue());
					byteRead[i++] = (byte)(Integer.valueOf(iotIpPiece[2]).intValue());
					byteRead[i++] = (byte)(Integer.valueOf(iotIpPiece[3]).intValue());
					
					int iotPort = this.paras.get("iotPort").asInt();
					byte[] iotPortByte = Utilty.getInstance().int2Bytes(iotPort, 2);
					byteRead[i++] = iotPortByte[0];
					byteRead[i++] = iotPortByte[1];

				} else if (this.cmdCode == 0x000B) { // 设置单灯UID

					String newUid = this.paras.get("newUid").asText().substring(0,7);
					byte[] newUidByte = newUid.getBytes("utf-8");
					for (byte b : newUidByte) {
						byteRead[i++] = b;
					}
					
//					byteRead[i++] = newUidByte[0];
//					byteRead[i++] = newUidByte[1];
//					byteRead[i++] = newUidByte[2];
//					byteRead[i++] = newUidByte[3];
//					byteRead[i++] = newUidByte[4];
//					byteRead[i++] = newUidByte[5];
//					byteRead[i++] = newUidByte[6];
//					byteRead[i++] = newUidByte[7];

				} else if (this.cmdCode == 0x000C) { // 设置单灯计量补偿

					byte[] voltageOffsetByte = Utilty.getInstance().int2Bytes(new Double(this.voltageOffset*10).intValue(), 2);
					byteRead[i++] = voltageOffsetByte[0];
					byteRead[i++] = voltageOffsetByte[1];
					
					byte[] currentOffsetByte = Utilty.getInstance().int2Bytes(new Double(this.currentOffset*10).intValue(), 2);
					byteRead[i++] = currentOffsetByte[0];
					byteRead[i++] = currentOffsetByte[1];
				}else {
					System.out.println(String.format("error cmdCode [%s] can not found in tobyte", this.cmdCode));
					return null;
				}
				
				byte[] tt= new byte[this.reqLength - 2];
				System.arraycopy(byteRead, 0, tt, 0, this.reqLength - 2);
				// CRC校验
				int crc = CRC16M.calculateCrc16(tt, byteRead.length - 2);
				byte[] byteCrc = Utilty.getInstance().int2Bytes(crc, 2);
				byteRead[i++] = byteCrc[0];
				byteRead[i++] = byteCrc[1];
				
				/*
				 * 应用服务器下发的控制命令，本例只有一条控制命令：SET_DEVICE_LEVEL 如果有其他控制命令，增加判断即可。
				 */

//				if (this.cmd.equals("SET_DEVICE_LEVEL")) {
//					int brightlevel = paras.get("value").asInt();
//					byte[] byteRead = new byte[5];
//					byteRead[0] = (byte) 0xAA;
//					byteRead[1] = (byte) 0x72;
//					byteRead[2] = (byte) brightlevel;
//
//					// 此处需要考虑兼容性，如果没有传mId，则不对其进行编码
//					// if (Utilty.getInstance().isValidofMid(mid)) {
//					// byte[] byteMid = new byte[2];
//					// byteMid = Utilty.getInstance().int2Bytes(mid, 2);
//					// byteRead[3] = byteMid[0];
//					// byteRead[4] = byteMid[1];
//					// }
//
					return byteRead;
//				}
			}

			/*
			 * 平台收到设备的上报数据，根据需要编码ACK，对设备进行响应，如果此处返回null，表示不需要对设备响应。
			 */
			else if (("cloudRsp").equals(this.msgType)) {
//	        	int requestCmdCode = Utilty.getInstance().bytes2Int(this.request, CMDCODE_INDEX, 2);
//	        	if(requestCmdCode == 0x0002){
//	        		byte[] byteCmdCode = Utilty.getInstance().int2Bytes(0x0102, 2);
//	        		request[CMDCODE_INDEX] = byteCmdCode[0];
//	        		request[CMDCODE_INDEX + 1] = byteCmdCode[1];
//	        		
//		        	// CRC校验
//					int crc = CRC16M.calculateCrc16(request, request.length - 2);
//					byte[] byteCrc = Utilty.getInstance().int2Bytes(crc, 2);
//					request[request.length-2] = byteCrc[0];
//					request[request.length-1] = byteCrc[1];
//					
//					return request;
//	        	}
				// 平台无需应答
				return null;
			}
			return null;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return null;
		}
	}

	private int setBaseValue(byte[] sendByte) throws Exception {

		int i = 0;
		// 帧头
		sendByte[i++] = (byte) '@';
		sendByte[i++] = (byte) '#';
		// 消息长度
		byte[] byteLen = Utilty.getInstance().int2Bytes(reqLength-4, 2);
		sendByte[i++] = byteLen[0];
		sendByte[i++] = byteLen[1];
		// 主版本
		sendByte[i++] = (byte) mainVersion;
		// 副版本
		sendByte[i++] = (byte) subVersion;
		// 单灯节点UID
		byte[] byteUid;
		if(this.uid.contains(",")){ // 如果是逗号分隔的多个uid，则换成广播地址；
			byteUid = new byte[] {(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff};
		}else{ // 否则是单个uid
			byteUid = this.uid.substring(0, 7).getBytes("ISO8859-1");
		}
		for (byte b : byteUid) {
			sendByte[i++] = b;
		}
		// 消息id
		byte[] byteMid = Utilty.getInstance().int2Bytes(mid, 2);
		sendByte[i++] = byteMid[0];
		sendByte[i++] = byteMid[1];
		// 指令码
		byte[] byteCmdCode = Utilty.getInstance().int2Bytes(cmdCode, 2);
		sendByte[i++] = byteCmdCode[0];
		sendByte[i++] = byteCmdCode[1];
		
		return i;
	}
	
	private int copyValue(byte[] srcByte, byte[] destByte, int destStart){
		int index=destStart;
		for(int i=0;i<srcByte.length;i++){
			index = i+destStart;
			destByte[index] = srcByte[0];
		}
		
		return index;
	}
	
	public static void main(String[] args) {
		ObjectMapper mapper = new ObjectMapper();
		String js = "{\"identifier\": \"123\",\"msgType\": \"cloudReq\",\"serviceId\": \"StreetLightBasic\",\"cmd\": \"SET_BRIGHTNESS\",\"mid\": 2016,\"paras\": {\"parameters\":{\"uid\":\"12345678\", \"brightness\": \"10\", \"cmdCode\":4}},\"hasMore\": 0}";
		
		try {
			ObjectNode readNode = (ObjectNode)mapper.readTree(js);
			CmdProcess cmdProcess = new CmdProcess(readNode);
			byte[] b = cmdProcess.toByte();
			System.out.println(Utilty.parseByte2HexStr(b));
//			
//			byte[] byteRead1 = Utilty.hexString2Bytes("40231200000048562D5445535430020002000000");
//			int crc1 = CRC16M.calculateCrc16(byteRead1, byteRead1.length - 2);
//			byte[] byteCrc1 = Utilty.getInstance().int2Bytes(crc1, 2);
//			System.out.println("byteRead1:" + Utilty.parseByte2HexStr(byteCrc1));
//			
//			
//			byte[] t = Utilty.hexString2Bytes("40231200000048562D54455354300200020000000877");
//			
//			ReportProcess reportProcess = new ReportProcess(t);
//			ObjectNode parseNode = reportProcess.toJsonNode();
//			System.out.println(parseNode.toString());
		}
		catch (JsonProcessingException e) {
//			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
			catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		////-------------------------------------------------------------
		CmdProcess cmd = new CmdProcess();
		cmd.cmdCode = 14645;
		cmd.uid = "HV-TEST0";
		cmd.reqLength = 22;
		cmd.mid = 13877 ;
		
//		
		byte[] byteRead = new byte[22];
		try {
			int i = cmd.setBaseValue(byteRead);
			
			byte[] alarmType = Utilty.getInstance().int2Bytes(0, 2);
			byteRead[i++] = alarmType[0];
			byteRead[i++] = alarmType[1];
			
			
			byte[] tt= new byte[cmd.reqLength - 2];
			System.arraycopy(byteRead, 0, tt, 0, cmd.reqLength - 2);
			System.out.println("bef crc:" + Utilty.parseByte2HexStr(tt));
			
			// CRC校验
			int crc = CRC16M.calculateCrc16(tt, cmd.reqLength - 2);
			byte[] byteCrc = Utilty.getInstance().int2Bytes(crc, 2);
			byteRead[i++] = byteCrc[0];
			byteRead[i++] = byteCrc[1];
			
			System.out.println("aft crc:" + Utilty.parseByte2HexStr(byteRead));
		} 
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
//		String dataString = "[{\"id\":123},{\"name\":\"tom\"}]";
//		JSONArray jsonArray = JSONArray.parseArray(dataString);
//		Object object=jsonArray.get(0);
//		JSONObject serviceData = JSONObject.parseObject(object.toString());
	}
}
